home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World's Largest Collection of Windows Software
/
The World's Largest Collection of Windows Software - Disc 1.iso
/
connect
/
_j2
/
wvnsc926
/
wvheader.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-21
|
38KB
|
1,442 lines
/* --- WVHEADER.C ---------------------------------------------
*
* This file contains the code necessary to create the initial skeleton
* version of an article, which will be edited by the user.
*
* Mark Riordan 24-JAN-1990
*/
/*
*
* $Id: wvheader.c 1.26 1994/09/16 00:42:53 jcooper Exp $
* $Log: wvheader.c $
* Revision 1.26 1994/09/16 00:42:53 jcooper
* cc-by-mail feature and cleanup for 92.6
*
* Revision 1.25 1994/08/24 18:40:15 mrr
* authorization enables post/mail
*
* Revision 1.24 1994/05/27 01:29:29 rushing
* unnecessary winundoc.h
*
* Revision 1.23 1994/02/24 21:31:49 jcoop
* jcoop changes
*
* Revision 1.22 1994/02/09 18:01:08 cnolan
* cnolan 90.2 changes
*
* Revision 1.21 1994/01/18 09:51:34 jcoop
* Use new version number scheme on X-Mailer header line
*
* Revision 1.20 1994/01/15 20:31:16 jcoop
* Font/color stuff and signature file handling
*
* Revision 1.19 1993/12/08 01:27:21 rushing
* new version box and cr lf consistency
*
* Revision 1.18 1993/08/25 18:53:17 mbretherton
* MRB merge, mail & post logging
*
*
* remove underscore for BC++ compile Bretherton
*
* Revision 1.17 1993/08/17 21:53:06 UNKNOWN
* Updated version to Version 0.82 (JD)
*
* Revision 1.16 1993/07/13 22:11:31 rushing
* strncpy crashing in parseaddress
*
* Revision 1.15 1993/07/06 21:09:50 cnolan
* win32 support
*
* Revision 1.14 1993/06/29 20:06:07 rushing
* use localtime for Date header
*
* Revision 1.13 1993/06/29 00:22:13 rushing
* correct rfc822/rfc1036 MakeArtHeaderDate function
*
* Revision 1.12 1993/06/28 17:51:21 rushing
* warnings
*
* Revision 1.11 1993/06/22 19:08:40 rushing
* remove warnings
*
* Revision 1.10 1993/06/22 16:46:33 bretherton
* robust parse_address
*
* Revision 1.9 1993/06/11 01:05:17 rushing
* new version number
*
* Revision 1.8 1993/06/11 00:11:26 rushing
* second merge from Matt Bretherton sources
*
*
* Revision 1.7 1993/05/24 23:34:12 rushing
* further refinements to header manipulation
* extend reuse of header formatting capabilities
*
*
* Revision 1.5 1993/05/18 22:10:45 rushing
* smtp support
*
* Revision 1.4 1993/05/06 19:44:10 rushing
* CompareStringNoCase was using _tolower rather than tolower.
* according to c70 docs, _tolower is undefined for letters that
* are not uppercase. Yikes!
*
* Revision 1.3 1993/04/30 21:17:01 rushing
* put the X-Newsreader: line back in.
*
* Revision 1.2 1993/03/30 20:07:37 rushing
* MAPI
*
* Revision 1.1 1993/02/16 20:54:22 rushing
* Initial revision
*
*
*/
#include <windows.h>
#include <windowsx.h>
#include "wvglob.h"
#include "winvn.h"
#pragma hdrstop
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#define MAXHEADERLINE 256
int NewDocType;
BOOL (*PostHeaderFuncs[])(TypDoc * Doc, char *Buf, long int BufLen) =
{
MakeArtHeaderFrom,
MakeArtHeaderNewsgroups,
MakeArtHeaderSubject,
/* MakeArtHeaderMessageID, */
/* MakeArtHeaderDate, */
MakeArtHeaderReferences,
MakeArtHeaderOrganization,
MakeArtHeaderReplyTo,
MakeArtHeaderNewsreader,
NULL
};
/*--- function GetHeaderLine -------------------------------------------
*
* Given a document, get a line from the header portion of that document
* whose prefix matches a given prefix. Prefix = first word in line.
* For instance, you might call this routine to say "Get the 'Subject:'"
* line from this document.
*
* Entry Doc points to the document whose header we are scanning.
* The header is all the lines up to the first blank line.
* Prefix is the character string which will identify the
* line we are seeking. It is the first word
* (blank-delimited) in a line in the header.
* BufLen is the number of bytes left in the buffer Buf.
*
* Exit Returns TRUE iff we returned a line.
* Buf if line was returned, contains that line, zero-
* terminated.
*/
BOOL
GetHeaderLine (Doc, Prefix, Buf, BufLen)
TypDoc *Doc;
char *Prefix;
char *Buf;
int BufLen;
{
char *bufptr = Buf;
TypBlock far *BlockPtr;
TypLine far *LinePtr;
unsigned int Offset;
HANDLE hBlock;
TypLineID MyLineID;
int found = FALSE;
TopOfDoc (Doc, &BlockPtr, &LinePtr);
while (ExtractTextLine (Doc, LinePtr, Buf, BufLen))
{
/* Is this a blank line signifying the end of the header? */
if (IsLineBlank (Buf))
break;
if (CompareStringNoCase (Buf, Prefix, strlen (Prefix)) == 0)
{
found = TRUE;
break;
}
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
return (found);
}
/*--- function CreatePostingWnd -----------------------------------------
*
* Create the window for composing the text of a posting,
* if it's OK to post.
*
* Entry Hwnd Handle to parnet window
* Doc points to the document to which we are posting
* a followup--NULL if it's a new posting.
*
* Exit Returns the handle of the newly-created window
* (zero if failure).
*/
HWND
CreatePostingWnd (hWnd,Doc, DocType)
HWND hWnd ;
TypDoc *Doc;
int DocType;
{
int ih;
BOOL found = FALSE;
BOOL AuthReq;
unsigned int width;
char *TitlePtr, *WndName;
if (DocType == DOCTYPE_POSTING)
{
AuthReq = AuthReqPost;
WndName = "WinVnPost";
PostDoc = Doc;
if (Doc)
{
TitlePtr = "Composing Followup Article";
}
else
{
TitlePtr = "Composing New Article";
}
for (ih = 0; !found && ih < MAXPOSTWNDS; ih++)
{
if (!WndPosts[ih].hWnd)
{
found = TRUE;
break;
}
}
}
else
{
AuthReq = AuthReqMail;
WndName = "WinVnMail";
MailDoc = Doc;
if (Doc)
{
TitlePtr = "Composing Reply Message";
}
else
{
TitlePtr = "Composing New Mail Message";
strcpy(AddressString,"") ;
}
for (ih = 0; !found && ih < MAXMAILWNDS; ih++)
{
if (!WndMails[ih].hWnd)
{
found = TRUE;
break;
}
}
}
if (found && AuthenticatePosting (AuthReq))
{
if (xScreen > 78 * ArtCharWidth)
{
width = 78 * ArtCharWidth;
}
else
{
width = xScreen - 2 * ArtCharWidth;
}
hWnd = CreateWindow (WndName,
TitlePtr,
WS_OVERLAPPEDWINDOW /* | WS_VSCROLL */ ,
/* Initial X pos */
ih * CharWidth,
/* Initial Y pos */
(int) (yScreen * 3 / 8) + (1 + ih) * LineHeight,
/* Initial X Width */
(int) width,
/* Initial Y height */
(int) (yScreen * 5 / 8) - (2 * LineHeight),
NULL,
NULL,
hInst,
NULL);
if (hWnd)
{
SetHandleBkBrush (hWnd, hArticleBackgroundBrush);
ShowWindow (hWnd, SW_SHOWNORMAL);
UpdateWindow (hWnd);
}
}
return (hWnd);
}
/*--- function CreatePostingText ------------------------------------------
*
* Create the text of the skeleton article to be edited by
* the user before posting. Display that text in an edit window.
*/
BOOL
CreatePostingText (Doc, hWndPost, hWndEdit, DocType)
TypDoc *Doc;
HWND hWndPost;
HWND hWndEdit;
int DocType;
{
char far *lpTextBuffer;
HANDLE hTextBuffer;
int nLines;
long lParam;
if (NULL == (hTextBuffer = ExtractPostingText(Doc,DocType)))
{
MessageBox (hWndPost, "Cannot allocate memory for text", "", MB_OK);
return FALSE;
}
lpTextBuffer = GlobalLock(hTextBuffer) ;
/* Set the edit window text to this skeleton article. */
SetWindowText (hWndEdit, lpTextBuffer);
FreePostingText (hTextBuffer);
nLines = (int) SendMessage (hWndEdit, EM_GETLINECOUNT, 0, 0L);
lParam = (long) ((long) nLines);
return TRUE;
}
/*--------- Extract the Text for the Posting ---------------------------
*
* Entry Doc points to the document to which we are posting
* a followup--NULL if it's a new posting. *
* DocType either build skeletal mail or posting document
*
* Exit a pointer to the unlocked memory area for skeletal posting
*
* Remember to call FreePosting Text to reclaim the memory allocated to
* the posting text
*/
HANDLE
ExtractPostingText (Doc, DocType)
TypDoc *Doc;
int DocType;
{
long int BytesLeft;
char far *lpTextBuffer;
BOOL (**HeaderFuncs) (TypDoc * Doc, char *Buf, long int BufLen);
char far *lpCurPtr;
HANDLE hTextBuffer;
BOOL gotline;
char line[MAXHEADERLINE];
int ifunc;
NewDocType = DocType;
if (DocType == DOCTYPE_POSTING)
{
HeaderFuncs = PostHeaderFuncs;
}
else
{
HeaderFuncs = MailCtrl.MailHeaderFuncs;
}
/* Compute the number of bytes we need to hold a straight ASCII representation
* of the initial text of the reply, and allocate a buffer of that size.
*/
if (Doc)
{
BytesLeft = (2 + NumBlocksInDoc (Doc)) * Doc->BlockSize;
}
else
{
BytesLeft = 3000;
}
if (NULL == (hTextBuffer = GlobalAlloc (GHND, (DWORD) BytesLeft)))
{
return ((HANDLE) NULL) ;
}
lpCurPtr = lpTextBuffer = GlobalLock (hTextBuffer);
for (ifunc = 0; HeaderFuncs[ifunc]; ifunc++)
{
gotline = (HeaderFuncs[ifunc]) (Doc, line, (long int) MAXHEADERLINE);
if (gotline)
{
AppendTextToEditBuf (line, &lpCurPtr, &BytesLeft);
}
}
MakeArtBody (Doc, &lpCurPtr, &BytesLeft, DocType);
GlobalUnlock (hTextBuffer);
return(hTextBuffer) ;
}
/*---------- FreePostingText ---------------------------------------------
*
* Free the memory of the skeletal posting text
*
*/
BOOL
FreePostingText (hTextBuffer)
HANDLE hTextBuffer;
{
GlobalUnlock (hTextBuffer);
GlobalFree (hTextBuffer);
strcpy(AddressString,"") ;
strcpy(NameString,"") ;
strcpy(DialogString,"") ;
return(TRUE) ;
}
/*--- functions MakeArtHeaderXXXXX ---------------------------------------
*
* Functions with names of the form MakeArtHeaderXxxxxx are all called
* the same way and have similar purposes. They are called to
* create and return a line of text that will become a line in
* the header of an article to be posted. The source of
* this information varies; it may be taken from an article
* being replied to, it may be taken from a configuration file,
* read from the system clock, etc.
*
* Entry Doc points to a document containing an article
* being replied to; NULL if we're not replying
* to an article.
* BufLen is the length of the output buffer.
*
* Exit Returns TRUE iff we returned a line.
* Buf contains the line, if any, terminated by a
* zero byte.
*/
/*--- function MakeArtHeaderSubject -------------------------------------
*
* Returned "Subject:"
*
*/
BOOL
MakeArtHeaderSubject (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
char from[MAXHEADERLINE];
char *fromptr;
CopyBuf ("Subject: ", &outptr, &BufLen);
if (Doc)
{
GetArtHeaderSubject (Doc, NULL, NULL);
// if (!DialogString[0]) // always allow reply-subject confirmation
if (NewDocType == DOCTYPE_POSTING) {
fromptr = from;
if (GetHeaderLine (Doc, "From:", from, MAXHEADERLINE-1))
{
NextToken (&fromptr);
ParseAddress (fromptr, CcAddress, MAXDIALOGSTRING , str, MAXINTERNALLINE ) ;
} else
CcAddress[0] = (char) NULL;
}
DialogBoxParam (hInst, "WinVnSubject", Doc->hDocWnd, lpfnWinVnSubjectDlg, (LPARAM)(NewDocType == DOCTYPE_POSTING));
}
else
{
DialogString[0] = (char) NULL;
CcAddress[0] = (char) NULL;
DialogBoxParam (hInst, "WinVnSubject", hWndConf, lpfnWinVnSubjectDlg, (LPARAM)(NewDocType == DOCTYPE_POSTING));
}
CopyBuf (DialogString, &outptr, &BufLen);
return (TRUE);
}
/*--- function GetArtHeaderSubject -------------------------------------
*
* Fill the DialogString global variable if a subject can be extracted
* of the form "Subject: Re: <previous subject>".
* If the article being replied to had a subject already starting
* with "Re:", the "Re:" is not repeated.
* returns FALSE as no line assembled
* if no previous subject is found SubjestString is ""
*/
GetArtHeaderSubject (Doc, NA, NALen)
TypDoc *Doc;
char *NA;
long int NALen;
{
char HeadLine[MAXHEADERLINE];
char *outptr = DialogString ;
char *headptr = HeadLine;
long int BufLen = MAXDIALOGSTRING ;
*outptr='\0' ;
if (Doc && ( GetHeaderLine (Doc, "Subject:", HeadLine, MAXHEADERLINE)))
{
NextToken (&headptr);
if (CompareStringNoCase (headptr, "Re:", 3) != 0)
{
CopyBuf ("Re: ", &outptr, &BufLen);
}
CopyBuf (headptr, &outptr, &BufLen);
}
return(FALSE) ;
}
#if 0
/*--- function MakeArtHeaderMessageID ----------------------------------
*
* Returned "Message-ID:" line is computed from the time and
* the ServerName (from Windows profile file). This needs to
* be improved.
*/
BOOL
MakeArtHeaderMessageID (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
#define MAXSERVERNAME 32
char ServerName[MAXSERVERNAME];
GetPrivateProfileString (szAppName, "ServerName", "titan.ksc.nasa.gov",
ServerName, MAXSERVERNAME, szAppProFile);
sprintf (Buf, "Message-ID: <%ld@%s>", time ((time_t *) NULL), ServerName);
return TRUE;
}
#endif
/*--- function MakeArtHeaderFrom ----------------------------------
*
* Returned "From:" is taken from Windows profile entries.
*/
BOOL
MakeArtHeaderFrom (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
CopyBuf ("From: ", &outptr, &BufLen);
if (MailAddress[0])
{
CopyBuf (MailAddress, &outptr, &BufLen);
}
else
{
CopyBuf ("<Unknown>", &outptr, &BufLen);
}
if (UserName[0])
{
CopyBuf (" (", &outptr, &BufLen);
CopyBuf (UserName, &outptr, &BufLen);
CopyBuf (")", &outptr, &BufLen);
}
return TRUE;
}
/*--- function MakeArtHeaderReplyTo -------------------------------
*
* Returned "Reply-To:" is taken from Windows profile entries.
*/
BOOL
MakeArtHeaderReplyTo (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
if (ReplyTo[0] && strcmp(ReplyTo, MailAddress))
{
CopyBuf ("Reply-To: ", &outptr, &BufLen);
CopyBuf (ReplyTo, &outptr, &BufLen);
return TRUE;
}
return FALSE;
}
/*--- function MakeArtHeaderTo ----------------------------------
*
* Returns a well formed "To:" line or if user selected cancel
* returns "To:" (blank) which if not edited will be rejected by
* the server.
*/
BOOL
MakeArtHeaderTo (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
char *outptr = Buf, *cptr = HeadLine;
GetArtHeaderTo(Doc,NULL,NULL);
if (!strcmp(AddressString, "")) {
DialogString[0]=(char)NULL;
while (!strcmp(DialogString,""))
if (!DialogBox (hInst, "WinVnMail", hWndConf, lpfnWinVnMailDlg))
break;
sprintf(HeadLine,"To: %s", DialogString);
}
else
sprintf(HeadLine,"To: %s", AddressString);
CopyBuf (HeadLine, &outptr, &BufLen);
return TRUE;
}
/*--- function GetArtHeaderTo ----------------------------------
*
* Simply returns contents for a "To:" Line
*
* Global Variables
* NameString and AddressString are extracted from the Document
* returns FALSE as no line has been assembled
*/
BOOL
GetArtHeaderTo (Doc, NA, NALen)
TypDoc *Doc;
char *NA;
long int NALen;
{
char HeadLine[MAXHEADERLINE];
char *cptr = HeadLine ;
BOOL gotwho;
char ReplyAddress[MAXDIALOGSTRING], ReplyName[MAXDIALOGSTRING];
if (Doc)
{
if (GetHeaderLine (Doc, "From:", HeadLine, MAXHEADERLINE))
{
NextToken (&cptr);
ParseAddress (cptr, AddressString,MAXDIALOGSTRING , NameString,MAXDIALOGSTRING ) ;
}
if (gotwho = GetHeaderLine (Doc, "Reply-To:", HeadLine, MAXHEADERLINE))
{
NextToken (&cptr);
ParseAddress (cptr, ReplyAddress,MAXDIALOGSTRING , ReplyName,MAXDIALOGSTRING ) ;
}
if (gotwho && strcmp (AddressString, ReplyAddress))
{
if (AddressString[0] && ConfirmReplyTo)
{
sprintf (str, "Use Reply-To: (%s) instead of\nFrom: (%s) in reply?",
ReplyAddress, AddressString);
if (MessageBox (Doc->hDocWnd, str, "Confirm Reply-To",
MB_YESNO|MB_ICONQUESTION) == IDNO)
gotwho = FALSE;
}
if (gotwho)
strcpy (AddressString, ReplyAddress);
}
}
return FALSE;
}
/*--- function ParseAddress --------------------------
* Scan the
* address field (null terminated ascii string)
* representing any email address and optional
* name
*
* and extract
* addressout which is the email address
* nameout which is the name (enclosed in parenthises)
*
*--------------------------------------------------------*/
void ParseAddress(headerline,addressout,addressoutlen,nameout,nameoutlen)
char *headerline ;
char *addressout ;
long int addressoutlen ;
char *nameout ;
long int nameoutlen ;
{ char *ptra = headerline , *ptrb, *ptrc ;
char *iptr , *optr;
int lastspace ;
long int adlen = addressoutlen - 1 ,nmlen = nameoutlen -1 ;
long int l;
nameout[0]=addressout[0]=0 ;
// Note parsing not strictly correct as anything in quotes '"'
// overrides the meaning of lexical constructs '<' and '('
// Seems this works and is robust but is now in the main
// group list read and should be extremely efficient
// suggest a single pass 'stream' parse more appropriate
// but is more work
if (ptrb=strchr(headerline,'<'))
{ // address enclosed in brackets
l=min(ptrb-ptra-1,nmlen) ;
if (l < 0) l = 0; /* this was killing print??? */
if (l>0)
{ // otherwise strncpy crashes
nmlen-=l ;
strncpy(nameout,ptra,(int)l) ;
nameout[l]=0;
}
if( ptrc=strchr(headerline,'>') )
{
if (nmlen >0)
{
strncpy(nameout+l,ptrc+1,(int)nmlen) ;
nameout[nameoutlen-1]=0 ;
}
l=min(ptrc-ptrb-1,adlen) ;
} else
{
l=adlen ;
}
if (l>0)
{
strncpy(addressout,ptrb+1,(int)l);
addressout[l]=0;
}
} else
if (ptrb=strchr(headerline,'('))
{ // name enclosed in braces
l=min(ptrb-ptra-1,adlen) ;
if (l>0)
{
adlen-=l ;
strncpy(addressout,ptra,(int)l) ;
addressout[l+1]=0;
}
if( ptrc=strchr(headerline,')'))
{
if (adlen > 0)
{
strncpy(addressout+l,ptrc+1,(int)adlen) ;
addressout[addressoutlen-1]=0 ;
}
l=min(ptrc-ptrb-1,nmlen) ;
} else
{
l=nmlen ;
}
if (l>0)
{
strncpy(nameout,ptrb+1,(int)l);
nameout[l]=0;
}
} else
{ // just an address
strncpy(addressout,ptra,(int)adlen) ;
addressout[addressoutlen-1]=0 ;
}
// Clean Name - remove multiple space and quotes
lastspace=TRUE ;
for(iptr=optr=nameout ; *iptr ; iptr++)
{ switch( *iptr)
{
case ' ':
if (!lastspace) *optr++=*iptr ;
lastspace=TRUE ;
break;
case '"':
break ;
default :
*optr++=*iptr ;
lastspace=FALSE ;
}
}
*optr=0 ;
// Clean Address
for(iptr=optr=addressout ; *iptr ; iptr++)
{ switch( *iptr)
{
case ' ':
break;
default :
*optr++=*iptr ;
lastspace=FALSE ;
}
}
*optr=0 ;
if (*nameout==0)
{ // if no name default to address
strncpy(nameout,addressout,(int)nmlen) ;
addressout[nameoutlen-1]=0 ;
}
}
/* original code for parsing address
char *adptr = addressout, *nmptr=nameout, *cptr = headerline;
char *tptr ;
if ( *cptr == '(' )
{ // skip Name in brackets
tptr = strchr(headerline,')') ;
if (tptr != NULL) cptr=tptr ;
NextToken(&cptr); // skip parenthesis and white space
}
while (*cptr && *cptr != ' ' && adlen)
{
*(adptr++) = *(cptr++);
adlen-- ;
}
*adptr = '\0';
cptr = strchr(headerline,'(');
if (cptr != NULL)
{
cptr++; // skip (
while (*cptr && *cptr != ')' && nmlen) // copy to )
{
if (*cptr != '"') // drop quote characters
{
*(nmptr++) = *(cptr);
nmlen--;
}
cptr++ ;
}
*nmptr = '\0';
}
else
{
strncpy( nmptr,addressout,(int)nmlen) ;
nmptr[nmlen+1]= '\0' ;
}
}
*/
/*--- function MakeArtHeaderOrganization ----------------------------------
*
* Returned "Organization:" line is gotten from the Windows
* profile file.
*/
BOOL
MakeArtHeaderOrganization (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
if (Organization[0])
{
CopyBuf ("Organization: ", &outptr, &BufLen);
CopyBuf (Organization, &outptr, &BufLen);
return (TRUE);
}
return FALSE;
}
/*--- function MakeArtHeaderNewsreader ----------------------------------
*
* Returned "Newsreader: " line is simply a constant.
*/
BOOL
MakeArtHeaderNewsreader (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char *outptr = Buf;
CopyBuf ("X-Newsreader: ", &outptr, &BufLen);
CopyBuf (WINVN_VERSION, &outptr, &BufLen);
/* easier than examining this closely */
/* CopyBuf ("\r", &outptr , &BufLen); */
return (TRUE);
}
/*--- function MakeArtHeaderXmailer ----------------------------------
*
* Returned "Mailer: " line is simply a constant.
*/
BOOL
MakeArtHeaderXmailer (TypDoc * Doc, char *Buf, long int BufLen)
{
char *outptr = Buf;
CopyBuf ("X-Mailer: ", &outptr, &BufLen);
// CopyBuf ("WinVN version 0.82 SMTP", &outptr, &BufLen);
CopyBuf (WINVN_VERSION, &outptr, &BufLen);
return (TRUE);
}
/*--- function MakeArtHeaderDate ----------------------------------
*
* Returned "Date:" line is computed from operating system time.
* Be sure to set the TZ environment variable correctly for
* "gmtime" to work properly. Typical setting: SET TZ=EST5
*/
BOOL
MakeArtHeaderDate (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
struct tm *timeptr;
time_t curtime;
static char * days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static char * months[] = { "Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"};
if (!getenv("TZ")) {
MessageBox (hWndConf,
"Timezone environment variable 'TZ' not set.\n"
"You must set this variable for your messages\n"
"to be timestamped correctly.\n"
"For example, you could add the following to your\n"
"'autoexec.bat' file:\n"
"set TZ=EST5EDT\n",
"Warning:",
MB_OK|MB_ICONHAND);
}
curtime = time ((time_t *) NULL);
timeptr = localtime (&curtime);
/* rfc1036&rfc822 acceptable format */
/* Mon, 29 Jun 93 02:15:23 GMT */
sprintf (Buf, "Date: %s, %.2d %s %.2d %.2d:%.2d:%.2d %s",
days[timeptr->tm_wday],
timeptr->tm_mday,
months[timeptr->tm_mon],
timeptr->tm_year,
timeptr->tm_hour,
timeptr->tm_min,
timeptr->tm_sec,
tzname[0]);
return TRUE;
}
/*--- function MakeArtHeaderReferences -----------------------------------
*
* Returned "References:" line contains all the previous article's
* References (if any), plus its Message-ID (if any).
*/
BOOL
MakeArtHeaderReferences (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
BOOL gotrefs;
BOOL gotmesID;
char *outptr = Buf;
char *headptr = HeadLine;
if (Doc)
{
gotrefs = GetHeaderLine (Doc, "References:", HeadLine, MAXHEADERLINE);
if (gotrefs)
{
CopyBuf (HeadLine, &outptr, &BufLen);
CopyBuf (" ", &outptr, &BufLen);
}
gotmesID = GetHeaderLine (Doc, "Message-ID:", HeadLine, MAXHEADERLINE);
if (gotmesID)
{
if (!gotrefs)
{
CopyBuf ("References: ", &outptr, &BufLen);
}
NextToken (&headptr);
CopyBuf (headptr, &outptr, &BufLen);
}
if (gotrefs || gotmesID)
return (TRUE);
}
return FALSE;
}
/*--- function MakeArtHeaderNewsgroups -----------------------------------
*
* Returned "Newsgroups:" line is simply a copy of previous article's.
*/
BOOL
MakeArtHeaderNewsgroups (Doc, Buf, BufLen)
TypDoc *Doc;
char *Buf;
long int BufLen;
{
char HeadLine[MAXHEADERLINE];
BOOL gotnews = FALSE;
char *outptr = Buf;
if (Doc)
{
gotnews = GetHeaderLine (Doc, "Newsgroups:", HeadLine, MAXHEADERLINE);
if (gotnews)
{
CopyBuf (HeadLine, &outptr, &BufLen);
}
}
if (!gotnews)
{
CopyBuf ("Newsgroups: ", &outptr, &BufLen);
CopyBuf (NewsgroupsPtr, &outptr, &BufLen);
}
return TRUE;
}
/*--- function MakeArtBody ----------------------------------------------
*
* Make the body of the article. This is null if there's no article
* to reply to, else it's text of the form:
* In article <Message-ID>, <user> says:
* >line 1
* >line 2
* > .....
*
* Entry Doc points to the article being replied to, else
* NULL if none.
* left is the number of bytes left in MesBuf.
*
* Exit MesBuf contains the added lines, and has been updated
* to point to just after the last added byte.
* left has been decremented appropriately.
* Return value is not used, for now.
*/
BOOL
MakeArtBody (Doc, MesBuf, left, DocType)
TypDoc *Doc;
char far **MesBuf;
long int *left;
int DocType;
{
HANDLE hBlock;
unsigned int Offset;
TypLineID MyLineID;
TypBlock far *BlockPtr;
TypLine far *LinePtr;
char mesID[MAXHEADERLINE];
char from[MAXHEADERLINE];
char line[MAXHEADERLINE];
BOOL gotmesID, gotfrom;
char *outptr = line;
char *fromptr = from;
char *mesptr = mesID;
register unsigned long i;
AppendTextToEditBuf ("", MesBuf, left); /* blank line after header */
/* Create the "In message xxx, yyy says:" line. */
if (Doc)
{
gotmesID = GetHeaderLine (Doc, "Message-ID:", mesID, MAXHEADERLINE);
if (gotmesID)
{
NextToken (&mesptr);
}
else
{
mesptr = "<Unknown>";
}
switch (DocType) {
case DOCTYPE_POSTING:
gotfrom = GetHeaderLine (Doc, "From:", from, MAXHEADERLINE);
if (gotfrom)
NextToken (&fromptr);
else
fromptr = "<Unknown>";
sprintf (line, "In article %s, %s says:", mesptr, fromptr);
break;
case DOCTYPE_MAIL:
sprintf (line, "In article %s, you say:", mesptr);
break;
}
AppendTextToEditBuf (line, MesBuf, left);
/* Skip past header of reply document. */
TopOfDoc (Doc, &BlockPtr, &LinePtr);
while (ExtractTextLine (Doc, LinePtr, line, MAXHEADERLINE) &&
!IsLineBlank (line))
{
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
/* Copy body of reply document into the body of this article, */
/* prepending a ">" to each line */
/* following line commented after a merge of MRB code (SMR)*/
/* line[0] = '>'; */
line[0] = QuoteLineInd ;
while (ExtractTextLine (Doc, LinePtr, line + 1, MAXHEADERLINE - 1))
{
AppendTextToEditBuf (line, MesBuf, left);
if (!NextLine (&BlockPtr, &LinePtr))
break;
}
UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
if (EnableSig && Signature->numLines > 0)
AppendTextToEditBuf ("", MesBuf, left); /* blank line before sig */
}
if (EnableSig)
{
for (i = 0; i < Signature->numLines; i++)
AppendTextToEditBuf (TextBlockLine(Signature, i), MesBuf, left);
}
return TRUE;
}
/*--- function CompareStringNoCase -------------------------------------
*
* Compare two strings, case insensitive.
*
* Entry str1, str2 are two strings to compare.
* slen is the number of characters to compare
* (but stop at a zero byte).
*
* Exit returns -1 if str1 is earlier in collating sequence,
* 0 if strings are equal, 1 otherwise
*/
int
CompareStringNoCase (str1, str2, slen)
char *str1;
char *str2;
int slen;
{
/* bug when either string is zero length mrb */
if (strlen(str1) < (unsigned) slen)
{
return(-1) ;
}
if (strlen(str2) < (unsigned) slen)
{
return(+1) ;
}
while (slen-- && *str1 && *str2)
{
if (tolower (*str1) < tolower (*str2))
{
return (-1);
}
else if (tolower (*str1) > tolower (*str2))
{
return (1);
}
str1++;
str2++;
}
return (0);
}
/*--- function CopyBuf -----------------------------------------------
*
* Copy a string into a buffer, being sure not to overrun the
* buffer.
*
* Entry instr points to the string to copy into the buffer,
* zero-terminated.
* buf is the buffer
* left is the number of bytes left in the buffer
* Exit buf contains the LWA+1 of the bytes copied into
* the output buffer. A Zero byte is stored
* into this location.
* left is the number of bytes left in the buffer.
*/
void
CopyBuf (instr, buf, left)
char *instr;
char **buf;
long int *left;
{
while (--(*left) > 1 && *instr)
{
*((*buf)++) = *(instr++);
}
if (*left > 0)
**buf = '\0';
}
/*--- function NextToken -----------------------------------------------
*
* Position a pointer to the next token in a string.
* Delimiters are space and tab.
*
* Entry cptr points to a position in a zero-terminated string.
*
* Exit Returns TRUE iff a next token was found.
* cptr points to the next token, if found--else
* it is unchanged.
*/
BOOL
NextToken (cptr)
char **cptr;
{
/* Skip to end of current token, if any. */
while (**cptr != ' ' && **cptr != '\t' && **cptr)
(*cptr)++;
/* Skip past white space. */
while (**cptr && (**cptr == ' ' || **cptr == '\t'))
(*cptr)++;
if (**cptr)
{
return (TRUE);
}
else
{
return (FALSE);
}
}
/*--- function AppendTextToEditBuf ----------------------------------------
*
* Appends a zero-terminated text line to a buffer to be given
* to an Edit window. Used in building messages to be displayed
* and edited by an Edit window.
*
* Entry instr points to a text line to add. It is terminated
* by a zero byte and does not end in CR or LF.
* left is the number of characters left in buf.
*
* Exit buf contains the line, terminated by CR and LF.
* buf now points to the next available byte.
* left has been decremented as appropriate.
*/
void
AppendTextToEditBuf (instr, buf, left)
char *instr;
char far **buf;
long int *left;
{
while (--(*left) > 0 && *instr)
{
*((*buf)++) = *(instr++);
}
if (--(*left) > 0)
*((*buf)++) = '\r';
if (--(*left) > 0)
*((*buf)++) = '\n';
if ((*left) > 0)
**buf = '\0';
}
/*--- function IsLineBlank ------------------------------------------------
*
* Determine whether a zero-terminated line is blank.
* "Blank" means it contains nothing but spaces and tabs.
*
* Entry line points to the line.
*
* Exit returns TRUE iff the line is blank.
*/
BOOL
IsLineBlank (line)
char far *line;
{
while (*line == ' ' || *line == '\t' || *line == '\n')
line++;
return (!(*line));
}
/*------------ editIntercept ----------------------------------
*
* the subclassed WindowProc for the edit component
*
* Capture key messages and pass them to parent
* as may contain accelerator information
*
*--------------------------------------------------------------*/
BOOL FAR PASCAL editIntercept(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND parWnd ;
BOOL res ;
if (msg == WM_KEYDOWN || msg == WM_KEYUP)
/* if it receives a keyboard event, pass it to your parent */
{
parWnd = GetParent(hwnd);
res = PostMessage(parWnd,msg, wParam,lParam );
}
/* and always let the edit control do its thing */
return (BOOL) CallWindowProc((WNDPROC)GetClassLong(hwnd, GCL_WNDPROC),
hwnd, msg, wParam , lParam);
}
/* --------------- prepareEditMenu -----------------
*
* Common (wvpost and wvmail) preparartion
* of edit menus
*
* -------------------------------------------------
*/
void prepareEditMenu(HWND parWnd,HWND hWndEdit)
{ DWORD dwResult ;
UINT action;
HMENU hMenu = GetMenu(parWnd);
dwResult = SendMessage (hWndEdit, EM_GETSEL, 0, 0L);
if ( HIWORD (dwResult) == LOWORD (dwResult) )
{ /* No selection to ROT,Copy or Cut */
action=MF_GRAYED ;
} else
{
action=MF_ENABLED ;
}
EnableMenuItem(hMenu,IDM_ROT13,action) ;
EnableMenuItem(hMenu,IDM_COPY,action) ;
EnableMenuItem(hMenu,IDM_CUT,action) ;
EnableMenuItem(hMenu,IDM_CLEAR,action) ;
if (IsClipboardFormatAvailable(CF_TEXT))
{
action=MF_ENABLED ;
} else
{ /* No Clip board contents to paste */
action=MF_GRAYED ;
}
EnableMenuItem(hMenu,IDM_PASTE,action) ;
if (SendMessage (hWndEdit, EM_CANUNDO, 0, 0L))
{
action=MF_ENABLED ;
} else
{ /* Undo Buffer is empty so cannot Undo changes */
action=MF_GRAYED ;
}
EnableMenuItem(hMenu,IDM_UNDO,action) ;
}
/* ---------------- function DoEditCommands -------------
*
* Command edit commands between wvpost and wvmail
*
* ------------------------------------------------------*/
DoEditCommands(HWND hWndEdit,WPARAM wParam,LPARAM lParam)
{
switch (LOWORD(wParam))
{
case IDM_UNDO:
SendMessage (hWndEdit, WM_UNDO, 0, 0L);
break;
case IDM_CUT:
SendMessage (hWndEdit, WM_CUT, 0, 0L);
break;
case IDM_COPY:
SendMessage (hWndEdit, WM_COPY, 0, 0L);
break;
case IDM_PASTE:
SendMessage (hWndEdit, WM_PASTE, 0, 0L);
break;
case IDM_CLEAR:
SendMessage (hWndEdit, WM_CLEAR, 0, 0L);
break;
case IDM_SELALL:
SendMessage (hWndEdit, EM_SETSEL, 0,
MAKELONG (0, 32767));
break;
case IDM_ROT13:
{ DWORD dwResult ;
WORD wStart, wEnd ;
char *editptr;
dwResult = SendMessage (hWndEdit, EM_GETSEL, 0, 0L);
wStart = LOWORD (dwResult) ;
wEnd = HIWORD (dwResult) ;
editptr = GetEditText (hWndEdit);
strnROT13(editptr + wStart, wEnd - wStart) ;
SetEditText (hWndEdit, editptr);
GlobalFreePtr (editptr);
InvalidateRect (hWndEdit, NULL, TRUE);
}
break;
default :
return(0) ; // signnify no action
}
return(1) ; // signify actions completed
}
/*
* function DoEditClose
* close down the edit window only if clean to close
* or user agrees to lose information
*
*/
void DoEditClose(HWND hWnd,int dirty)
{
if ( dirty == DT_DIRTY)
{
if (MessageBox(hWnd, "Are you sure you want to exit?", "Unsaved Work",
MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
DestroyWindow(hWnd);
}
else
DestroyWindow(hWnd);
}